//; ---------------------------------------------------------------------------
//; Object 40 - Moto Bug enemy (GHZ)
//; ---------------------------------------------------------------------------

#include "motobug.h"

#include "../../sprite.h"
#include "../../objectsystemNEWER.h"
#include "../../collision.h"

static object *obj;

//; ---------------------------------------------------------------------------
//; Animation script - Motobug enemy
//; ---------------------------------------------------------------------------

byte stand[3]  = { 0xF, 2, afEnd };
byte walk[6]   = {   7, 0, 1, 0, 2, afEnd };
byte smoke[13] = {    1, 3, 6, 3, 6, 4, 6, 4, 6, 4, 6, 5, afRoutine };

byte *Ani_Moto[3] = { stand, walk, smoke };

//; ---------------------------------------------------------------------------
//; Sprite mappings - Moto Bug enemy (GHZ)
//; ---------------------------------------------------------------------------
byte moto1[21] = { 4,
		 0xF0, 0xD, 0,   0, 0xEC,
		 0,    0xC, 0,   8, 0xEC,
		 0xF8,   1, 0, 0xC,  0xC,
		 8,	 8, 0, 0xE, 0xF4
};
byte moto2[21] = { 4,
		 0xF1, 0xD, 0,    0, 0xEC,
		 1,    0xC, 0,    8, 0xEC,
		 0xF9,   1, 0,  0xC,  0xC,
		 9,	 8, 0, 0x11, 0xF4
};
byte moto3[26] = { 5,
		 0xF0, 0xD, 0,    0, 0xEC,
		 0,    0xC, 0, 0x14, 0xEC,
		 0xF8,   1, 0,	0xC, 0xC,
		 8,	 4, 0, 0x18, 0xEC,
		 8,	 4, 0, 0x12, 0xFC
};
byte smoke1[6] = { 1,
		 0xFA,   0, 0, 0x1A, 0x10
};
byte smoke2[6] = { 1,
		 0xFA,   0, 0, 0x1B, 0x10
};
byte smoke3[6] = { 1,
		 0xFA,   0, 0, 0x1C, 0x10
};
byte blank[1] = { 0 };

byte *Map_Moto[7] = { moto1,  moto2,  moto3, 
                     smoke1, smoke2, smoke3,
		     blank
};

//----
void (*Moto_Index[4])() = { Moto_Main, Moto_Action, Moto_Animate, Moto_Delete };

//MotoBug:				; XREF: Obj_Index
void MotoBug(object *_obj)
{
    obj = _obj;

    //moveq	#0,d0
    //move.b	obRoutine(a0),d0
    byte routine = obj->Routine/2;

    //move.w	Moto_Index(pc,d0.w),d1
    //jmp	        Moto_Index(pc,d1.w)
    (*Moto_Index[routine])();
}




//Moto_Main:	; Routine 0
void Moto_Main()
{
    //move.l	#Map_Moto,obMap(a0)
    obj->Map = Map_Moto;
	
    //move.w	#$4F0,obGfx(a0)
    obj->Gfx = 0x4F0;

    //move.b	#4,obRender(a0)
    obj->Render = 4;

    //move.b	#4,obPriority(a0)
    obj->Priority = 4;

    //move.b	#$14,obActWid(a0)
    obj->ActionWidth = 0x14;

    //tst.b	obAnim(a0)	; is object a smoke trail?
    //bne.s	@smoke		; if yes, branch
    if (obj->Anim == 0)
    {	
        //move.b	#$E,obHeight(a0)
        obj->Height = 14;

	//move.b	#8,obWidth(a0)
        obj->Width = 8;

	//move.b	#$C,obColType(a0)
        obj->ColType = 0xC;

	//bsr.w	ObjectFall
        ObjectFall(obj);

	//jsr	ObjFloorDist 
        signed short floorDist = ObjFloorDist(obj);
		
        //tst.w	d1
	//bpl.s	@notonfloor
        if (floorDist < 0)
        {
	    //add.w	d1,obY(a0)	; match	object's position with the floor
	    obj->Y = obj->Y + floorDist;

            //move.w	#0,obVelY(a0)
            obj->VelocityY = 0;

	    //addq.b	#2,obRoutine(a0) ; goto Moto_Action next
            obj->Routine = obj->Routine + 2;

	    //bchg	#0,obStatus(a0)
            obj->Status = obj->Status ^ 1;

        }
	//@notonfloor:
	//rts
    }	
    //; ===========================================================================
    else
    {
        //@smoke:
	//addq.b	#4,obRoutine(a0) ; goto Moto_Animate next
        obj->Routine = obj->Routine + 4;

	//bra.w	Moto_Animate
        Moto_Animate();
    }
}   //; ===========================================================================

#define time 0x30
#define smokedelay 0x33
void (*Moto_ActIndex[2])() = { move, findfloor };
		
//Moto_Action:	; Routine 2
void Moto_Action()
{
    //moveq	#0,d0
    //move.b	ob2ndRout(a0),d0
    byte secondRoutine = obj->secondRoutine;

    //move.w	Moto_ActIndex(pc,d0.w),d1
    //jsr	Moto_ActIndex(pc,d1.w)
    (*Moto_ActIndex[secondRoutine/2])();

    //lea	(Ani_Moto).l,a1
    byte **aniScript = Ani_Moto;

    //bsr.w	AnimateSprite
    AnimateSprite(obj, aniScript);

    //include	"_incObj\sub RememberState.asm" ; Moto_Action terminates in this file
    RememberState(obj);
}

//@move:
void move()
{
    //subq.w	#1,@time(a0)	; subtract 1 from pause	time
    ptrsubobjvariableword(time, obj, 1);
	
    //bpl.s	@wait		; if time remains, branch
    if ((signed short)ptrgetobjvariableword(time, obj) < 0)
    {
        //addq.b	#2,ob2ndRout(a0)
        obj->secondRoutine = obj->secondRoutine + 2;

	//move.w	#-$100,obVelX(a0) ; move object to the left
        obj->VelocityX = -0x100;

	//move.b	#1,obAnim(a0)
        obj->Anim = 1;

        byte oldStatus = obj->Status;
	//bchg	#0,obStatus(a0)
        obj->Status = obj->Status ^ 1;

	//bne.s	@wait
	if ((oldStatus & 1) == 0)
        {
            //neg.w	obVelX(a0)	; change direction
            obj->VelocityX = -obj->VelocityX;
        }
	 
    }    
    //@wait:
    //rts	
}   //; ===========================================================================

//@findfloor:
void findfloor()
{
    //bsr.w	SpeedToPos
    SpeedToPos(obj);

    //jsr	ObjFloorDist
    signed short floorDist = ObjFloorDist(obj);

    //cmpi.w	#-8,d1
    //blt.s	@pause
    //cmpi.w	#$C,d1
    //bge.s	@pause
    if ((floorDist >= -8) && (floorDist < 12))
    {
        //add.w	d1,obY(a0)	; match	object's position with the floor
        obj->Y = obj->Y + floorDist;
	
	//subq.b	#1,@smokedelay(a0)
        obj->Variables[smokedelay - 0x28] = obj->Variables[smokedelay - 0x28] - 1;

	//bpl.s	@nosmoke
        if ((signed char)obj->Variables[smokedelay - 0x28] < 0)
        {
	    //move.b	#$F,@smokedelay(a0)
            obj->Variables[smokedelay - 0x28] = 15;

	    //bsr.w	FindFreeObj
            object *smoke = FindFreeObj();

	    //bne.s	@nosmoke
            if (smoke->ID == 0)
            { 
	        //move.b	#id_MotoBug,0(a1) ; load exhaust smoke object
		smoke->ID = id_MotoBug;

                //move.w	obX(a0),obX(a1)
                smoke->X = obj->X;

		//move.w	obY(a0),obY(a1)
		smoke->Y = obj->Y;

                //move.b	obStatus(a0),obStatus(a1)
		smoke->Status = obj->Status;

                //move.b	#2,obAnim(a1)
                smoke->Anim = 2;
            }
        }
    
	//@nosmoke:
	//rts
    }
    else	
    {
        //@pause:
	//subq.b	#2,ob2ndRout(a0)
        obj->secondRoutine = obj->secondRoutine - 2;

	//move.w	#59,@time(a0)	; set pause time to 1 second
        ptrsetobjvariableword(time,obj,59);

	//move.w	#0,obVelX(a0)	; stop the object moving
        obj->VelocityX = 0;

	//move.b	#0,obAnim(a0)
        obj->Anim = 0;

    }   //rts	
 
}   //; ===========================================================================

//Moto_Animate:	; Routine 4
void Moto_Animate()
{
    //lea	(Ani_Moto).l,a1
    byte **aniScript = Ani_Moto;
	
    //bsr.w	AnimateSprite
    AnimateSprite(obj, aniScript);

    //bra.w	DisplaySprite
    DisplaySprite(obj);

}   //; ===========================================================================

//Moto_Delete:	; Routine 6
void Moto_Delete()
{
    //bra.w	DeleteObject
    DeleteObject(obj);
}
